package com.bluegalaxy.nhb.snapi.controller.api.ck;

import com.alibaba.fastjson.JSONObject;
import com.bluegalaxy.nhb.service.AnalyseSqlService;
import com.bluegalaxy.nhb.snservice.common.utils.DateUtil;
import com.bluegalaxy.nhb.snservice.common.utils.StringUtil;
import com.bluegalaxy.nhb.snservice.domain.constant.AppConstant;
import com.bluegalaxy.nhb.snservice.domain.vo.api.R;
import com.bluegalaxy.nhb.snservice.domain.vo.api.ck.FunnelParamVO;
import com.bluegalaxy.nhb.snservice.domain.vo.api.ck.FunnelQueryResVO;
import com.bluegalaxy.nhb.snservice.domain.vo.api.ck.KeepParamVO;
import com.bluegalaxy.nhb.snservice.service.ck.FunnelService;
import com.bluegalaxy.nhb.snservice.service.ck.KeepService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static com.bluegalaxy.nhb.snservice.domain.constant.CkConstant.m_funnel;
import static com.bluegalaxy.nhb.snservice.domain.constant.CkConstant.queryItems;

/**
 * 漏斗分析
 */
@RestController
@RequestMapping(AppConstant.APPLICATION_NAME+"/funnel")
@Api(value = "漏斗分析", tags = "漏斗分析API")
public class FunnelController {
    private static Log log = LogFactory.getLog(FunnelController.class);

    @Autowired
    private FunnelService funnelService;
    @Resource
    private AnalyseSqlService sqlService;


    @ResponseBody
    @PostMapping("/findFunnel")
    @ApiOperation(value = "查询漏斗分析", notes = "查询漏斗分析列表")
    public R findFunnel(@RequestBody FunnelParamVO paramVO) {
        log.info("findFunnel param参数："+JSONObject.toJSONString(paramVO));

        Integer windowsFunnel = null;
        String funnelUnit = StringUtil.isEmpty(paramVO.getWindowFunnelUnit())?"day":paramVO.getWindowFunnelUnit();
        switch (funnelUnit){
            case "day":
                windowsFunnel = paramVO.getWindowFunnel()*24*60*60*1000;
            case "hour":
                windowsFunnel = paramVO.getWindowFunnel()*60*60*1000;
            case "min":
                windowsFunnel = paramVO.getWindowFunnel()*60*1000;
//            case "week":
//            case "month":
            default:
                windowsFunnel = paramVO.getWindowFunnel()*24*60*60*1000;
        }
        paramVO.setWindowFunnel(windowsFunnel);

        List<String> dateLists = DateUtil.getBetweenStrDates(paramVO.getStartDate(),paramVO.getEndDate());
        paramVO.setDateList(dateLists);

        paramVO.setConditionSql(sqlService.analyseSql(paramVO.getJsonParam(),m_funnel,queryItems));

        long start = System.currentTimeMillis();
        List<FunnelQueryResVO> resList = new ArrayList<>();
        int size = dateLists.size();
        int length = 10;
        if (dateLists.size() > length){
            int count = size % length != 0 ? size / length + 1 : size / length;
            for (int i = 0; i < count; i++) {
                List<String> subList = dateLists.subList(i * length, ((length + i * length) < size ? (length + i * length) : size));
                paramVO.setDateList(subList);
                List<FunnelQueryResVO> mapList = funnelService.selectFunnel(paramVO);
                resList.addAll(mapList);
            }
        }else{
            resList=funnelService.selectFunnel(paramVO);
        }

        long end = System.currentTimeMillis();
        log.info("查询时长："+(end - start));
//        log.info("resList:"+resList);
        Map<String, List<FunnelQueryResVO>> mapList = resList.stream().collect(
                Collectors.groupingBy(a -> a.getResDate()));
        List<FunnelQueryResVO> allResList = new ArrayList<>();
        //补充没有日期和没有事件的数据
        paramVO.getDateList().forEach(d ->{
            List<String> eventList = paramVO.getFunnelEvents();
            if (mapList.containsKey(d)){
                List<FunnelQueryResVO> rdateList = mapList.get(d);
                if (eventList.size() != rdateList.size()){
                    for (int i =0 ;i<rdateList.size();i++){
                        FunnelQueryResVO vo = rdateList.get(i);
                        vo.setEventCode(eventList.get(i));
                        vo.setEventName(eventList.get(i));
                    }
                    int eventSize = eventList.size();
                    int dataSize = rdateList.size();
                    int diffSize = eventSize - dataSize;
                    for (int i =0 ;i<diffSize;i++){
                        int index = i+dataSize;
                        FunnelQueryResVO vo = new FunnelQueryResVO(d,index,0,eventList.get(index),eventList.get(index));
                        rdateList.add(vo);
                    }
                }else {
                    int i=0;
                    for (FunnelQueryResVO resVO : rdateList){
                        resVO.setEventCode(eventList.get(i));
                        resVO.setEventName(eventList.get(i));
                        i++;
                    }
                }

                allResList.addAll(rdateList);

            }else{
                List<FunnelQueryResVO> tempResList = initEmptyList(d, eventList);
                allResList.addAll(tempResList);
            }
        });
        if (allResList.isEmpty()){
            return R.data(allResList);
        }
        List<FunnelQueryResVO> sortList = allResList.stream().sorted(Comparator.comparing(FunnelQueryResVO::getResDate)).collect(Collectors.toList());
        return R.data(sortList);
    }

    private List<FunnelQueryResVO> initEmptyList(String eventDate,List<String> events){
        List<FunnelQueryResVO> tempResList = new ArrayList<>();
        int i=0;
        for (String e : events){
            i++;
            FunnelQueryResVO vo = new FunnelQueryResVO(eventDate,i,0,e,e);
            tempResList.add(vo);
        }
        return tempResList;
    }

    @ResponseBody
    @PostMapping("/findUser")
    @ApiOperation(value = "查询漏斗分析用户列表", notes = "查询漏斗分析用户列表")
    public R findFunnelUser(@RequestBody FunnelParamVO paramVO) {
        log.info("findFunnel param参数："+JSONObject.toJSONString(paramVO));

        Integer windowsFunnel = null;
        String funnelUnit = StringUtil.isEmpty(paramVO.getWindowFunnelUnit())?"day":paramVO.getWindowFunnelUnit();
        switch (funnelUnit){
            case "day":
                windowsFunnel = paramVO.getWindowFunnel()*24*60*60*1000;
            case "hour":
            case "week":
            case "month":
            default:
                windowsFunnel = paramVO.getWindowFunnel()*24*60*60*1000;
        }
        paramVO.setWindowFunnel(windowsFunnel);
        paramVO.setDateList(DateUtil.getBetweenStrDates(paramVO.getStartDate(),paramVO.getEndDate()));

        long start = System.currentTimeMillis();
        List<Map<String,Object>> resList=funnelService.selectFunnelUser(paramVO);
        long end = System.currentTimeMillis();
        log.info("查询时长："+(end - start));

        return R.data(resList);
    }


}
